//
//  StoneCache.m
//  StoneAPI
//
//  Created by 陈小东 on 15/3/14.
//  Copyright (c) 2015年 _____stone_chenxiaodong_____. All rights reserved.
//

#import "StoneCache.h"
#import <CommonCrypto/CommonDigest.h>
#import <sys/stat.h>
#import <NSString+Nomal.h>

@interface StoneCache()
@property (nonatomic,strong,readwrite) NSCache * memoryCache;
@property (nonatomic,strong) dispatch_queue_t ioQueue;
@property (nonatomic,copy) NSString * filePath;
@end
#define DIR_NAME @"Stone.PersianCat.cacheDir"
#define FILE_PATH(key) [self.filePath stringByAppendingPathComponent:key]
@implementation StoneCache
static StoneCache * _instance;
+(StoneCache *)sharedCache
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[StoneCache alloc]init];
    });
    return _instance;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (id)init
{
    self = [super init];
    if (self)
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        self.filePath = [paths[0] stringByAppendingPathComponent:DIR_NAME];
        NSFileManager * fileManager = [NSFileManager defaultManager];
        BOOL exist =  [fileManager fileExistsAtPath:self.filePath];
        if(!exist)
        {
            NSError * error = nil;
            [fileManager createDirectoryAtPath:self.filePath
                   withIntermediateDirectories:NO
                                    attributes:nil
                                         error:&error];
        }
        self.ioQueue = dispatch_queue_create("JZ.JZ.PersianCat.queue", DISPATCH_QUEUE_SERIAL);
        self.memoryCache = [NSCache new];
        self.memoryCache.name = DIR_NAME;
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(clearMemory)
                                                     name:UIApplicationDidReceiveMemoryWarningNotification
                                                   object:nil];
    }
    return self;
}

-(void)clearMemory
{
    [self.memoryCache removeAllObjects];
}

-(void)setObject:(id<NSCoding>)object
          forKey:(NSString*)key
{
    if (!object)
        return;
    dispatch_async(self.ioQueue, ^()
                   {
                       NSString * keyMD5 = [key MD5_32];
                       NSString * path = FILE_PATH(keyMD5);
                       [NSKeyedArchiver archiveRootObject:object toFile:path];
                       [self.memoryCache setObject:object
                                            forKey:keyMD5];
                   });
}
-(id)objectForKey:(NSString*)key
{
    NSString * keyMD5 = [key MD5_32];
    id obj = [self.memoryCache objectForKey:keyMD5];
    if(obj)
        return obj;
    else{
        obj = [NSKeyedUnarchiver unarchiveObjectWithFile:FILE_PATH(keyMD5)];
        if(obj)
            [self.memoryCache setObject:obj
                                 forKey:keyMD5];
    }
    return obj;
}

-(void)removeAllDiskWithPercentBlock:(percentBlock)percentblock
                         finishBlock:(finishBlock)finishblock
{
    dispatch_async(self.ioQueue, ^()
                   {
                       NSError * error;
                       NSFileManager * manager= [NSFileManager defaultManager];
                       NSArray * contents =  [manager contentsOfDirectoryAtPath:FILE_PATH(@"")
                                                                          error:&error];
                       NSUInteger fileCount = contents.count;
                       NSUInteger removedCount= 0;
                       if(error&&percentblock)
                           percentblock(0,error);
                       for (NSString * content in  contents)
                       {
                           error = nil;
                           [manager removeItemAtPath:FILE_PATH(content)
                                               error:&error];
                           if(error){
                               if(percentblock)
                                   percentblock(removedCount/(CGFloat)fileCount,error);
                           }else{
                               removedCount++;
                               if(percentblock)
                                   percentblock(removedCount/(CGFloat)fileCount,nil);
                           }
                       }
                       if (finishblock) {
                           dispatch_async(dispatch_get_main_queue(), finishblock);
                       }
                   });
}

-(uint64_t)sizeOfCacheInDisk
{
    NSString * filePath = self.filePath;
    BOOL diskMode = NO;//是否为文件在磁盘下所占用的大小
    uint64_t totalSize = 0;
    NSMutableArray *searchPaths = [NSMutableArray arrayWithObject:filePath];
    while ([searchPaths count] > 0)
    {
        @autoreleasepool
        {
            NSString *fullPath = [searchPaths objectAtIndex:0];
            [searchPaths removeObjectAtIndex:0];
            
            struct stat fileStat;
            if (lstat([fullPath fileSystemRepresentation], &fileStat) == 0)
            {
                if (fileStat.st_mode & S_IFDIR)
                {
                    NSArray *childSubPaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:fullPath error:nil];
                    for (NSString *childItem in childSubPaths)
                    {
                        NSString *childPath = [fullPath stringByAppendingPathComponent:childItem];
                        [searchPaths insertObject:childPath atIndex:0];
                    }
                }else
                {
                    if (diskMode)
                        totalSize += fileStat.st_blocks*512;
                    else
                        totalSize += fileStat.st_size;
                }
            }
        }
    }
    
    return totalSize;
}


@end
